/**
 * @(#)QueryForm.java Dec 28, 2009
 *   
 * Copyright  (c) 2009-2010 Wilmar IT Service,  Inc.   
 * All  rights  reserved.   
 * TODO
 */

package com.wilmar.process.entity.query;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Array;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

import com.wilmar.common.util.PageinationEntity;
import com.wilmar.process.core.ProcessSystemDeclareKeys;

/**
 * 所有查询表单的父类,涵盖了分页信息
 * 
 * @author MaKuBEX Email:makubexnet@gmail.com
 * @version 1.0.0
 */
public abstract class QueryObject implements Serializable {

	/**
	 * @serialField
	 */
	private static final long serialVersionUID = 35481390945571403L;

	/**
	 * 分页信息
	 */
	protected PageinationEntity pageination;

	/**
	 * @return the pageination
	 */
	public PageinationEntity getPageination() {
		return pageination;
	}

	/**
	 * @param pageination
	 *            the pageination to set
	 */
	public void setPageination(PageinationEntity pageination) {
		this.pageination = pageination;
	}

	/**
	 * 从Array数组中加载属性
	 * 
	 * @param propertiesSequence
	 *            属性循序
	 * @param properties
	 *            属性值
	 * @throws NoSuchFieldException
	 *             如果类中并没有对应的属性
	 * @throws NoSuchMethodException
	 *             如果类中并没有对应的属性的set方法
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public void loadFromArrays(String[] propertiesSequence, Array... properties)
			throws NoSuchFieldException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		if (propertiesSequence.length != properties.length) {
			throw new IllegalArgumentException(
					"The count of properties do not match with the count of properties' values!");
		}
		for (int index = 0; index < propertiesSequence.length; index++) {
			String propName = propertiesSequence[index];
			Array values = properties[index];
			Class<? extends QueryObject> clazz = this.getClass();
			String methodName = ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROPERTIE_SETTER_PREFIX
					+ this.fristCharToUpCase(propName);
			try {
				Field propField = clazz.getDeclaredField(propName);
				Method setterMethod = clazz.getMethod(methodName, propField
						.getType());
				setterMethod.invoke(clazz, values);
			} catch (SecurityException e) {
				e.printStackTrace();
				throw e;
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
				throw e;
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
				throw e;
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
				throw e;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				throw e;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				throw e;
			}
		}
	}

	/**
	 * 将一个QueryObject或其子类转换成包含存储过程需要的数组参数对象
	 * 
	 * @param datatypeSequence
	 *            参数与参数类型对应关系
	 * @param databaseConnection
	 *            Oracle数据库连接
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InvocationTargetException
	 * @throw IllegalAccessException
	 * @throw SQLException
	 * @throw NoSuchFieldException
	 * @throws IllegalArgumentExceptio
	 */
	public Map<String, Object> format(Map<String, String> datatypeSequence,
			Connection databaseConnection) throws SecurityException,
			NoSuchMethodException, IllegalArgumentException,
			NoSuchFieldException, SQLException, IllegalAccessException,
			InvocationTargetException {
		Map<String, Object> result = new HashMap<String, Object>();
		Class<? extends QueryObject> clazz = this.getClass();
		Iterator<String> keySet = datatypeSequence.keySet().iterator();
		while (keySet.hasNext()) {
			String fieldsName = keySet.next();
			String type = datatypeSequence.get(fieldsName);
			Method getter = clazz
					.getMethod(ProcessSystemDeclareKeys.PROCESS_SYSTEM_PROPERTIE_GETTER_PREFIX
							+ this.fristCharToUpCase(fieldsName));
			if (clazz.getDeclaredField(fieldsName).getType().isArray()) {
				ArrayDescriptor desc = ArrayDescriptor.createDescriptor(type,
						databaseConnection);
				ARRAY vArray = new ARRAY(desc, databaseConnection, getter
						.invoke(this));
				result.put(fieldsName, vArray);
			} else {
				result.put(fieldsName, getter.invoke(this));
			}
		}
		return result;
	}

	private String fristCharToUpCase(String source) {
		String part_1 = source.substring(0, 1);
		String part_2 = source.substring(1);
		String target = part_1.toUpperCase() + part_2;
		return target;
	}
}
